/**
  *  This file is part of GlToolkit project https://code.google.com/p/gltoolkit/

  *  Copyright (C) 2010 Synble Ltd.
  *  All rights reserved.
  *  
  *  This library is provided 'as-is', without any express or implied
  *  warranty. In no event will the authors be held liable for any damages
  *  arising from the use of this software.
  *  
  *  Permission to use and alter this library requires a valid agreement
  *  with Synble Ltd and GetLocalization.com.
  *  
  *  You can use (including commercial applications) and alter this 
  *  library freely under the GetLocalization.com terms of service.
  *  Altered parts should be clearly marked as such.  
  *  
  */

#ifndef LOCENV_H
#define LOCENV_H

// INCLUDES
#include <e32std.h>
#include <e32base.h>
#include <coemain.h>
#include <http\mhttpdatasupplier.h>
#include <http\mhttptransactioncallback.h>
#include <http\mhttpauthenticationcallback.h>
#include <es_sock.h>
#include <BARSREAD.H>
#include <stringloader.h>
#include <aknprogressdialog.h>

class CLocString;
class CAknSettingItemList;
class CAknEnumeratedTextPopupSettingItem;
class CAknWaitDialog;

#define _LL(s) CLocEnv::Static()->GetString(_L(s))
#define LS(s) CLocEnv::Static()->GetString(s)

/**
 *  CLocEnv
 * 
 */
class CLocEnv: public CCoeStatic
	{
	public:
		// Constructors and destructor
	
		/**
		 * Destructor.
		 */
		virtual ~CLocEnv();
	
		/**
		 * Return localization environment. 
		 */
		IMPORT_C static CLocEnv* Static();
		
	public:
		/**
		 * Init language, this should be called when app is started or language is changed.
		 * Synchronous for now, can take some time with huge localization files and slow memory cards.
		 */
		void InitLanguageL();
		
		/**
		 * Will return corresponding localized string. Original string returned
		 * if localized version is not found. 
		 */
		TPtrC GetString(const TDesC& aString);
		
		/**
		 * Will translate all the menu panes. Call this in your AppUi/View DynInitMenuPaneL().
		 */
		void DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane);
		
		/**
		 * CAknSettingItemList does not provide functionality to modify strings after they are loaded from
		 * resources so this function will do the construction and translate the strings. 
		 */
		void ConstructSettingItemListL(CAknSettingItemList* aList, TInt aResId);
		
		/**
		 * Translate CAknEnumeratedTextPopupSettingItem. 
		 */
		void TranslateEnumeratedTextPopupSettingItem(CAknEnumeratedTextPopupSettingItem* item);
		
		/**
		 * Helper function to get correct language filename.
		 */
		void GetLanguageFile(TDes& aPathAndName);
		                
	private:
	
		/**
		 * Constructor for performing 1st stage construction
		 */
		CLocEnv();
	
		/**
		 * EPOC default constructor for performing 2nd stage construction
		 */
		void ConstructL();
		
		/**
		 * Helper function to calculate hash for the string.
		 */
		TUint32 HashPJW(const TDesC& aString);
	private:
		RPointerArray<CLocString> iCache;
	
	};

class CLocString : public CBase
	{
	public:
		CLocString(TInt32 aCheckSum, HBufC* aData) :
			iCheckSum(aCheckSum),
			iData(aData)
			{}
		
		~CLocString()
			{
			delete iData;
			}
		
		static TBool IsEqual(const CLocString& aLeft, const CLocString& aRight);
		static TInt Compare(const CLocString& aLeft, const CLocString& aRight);
		static TInt FastCompare(const TUint32* aCheckSum, const CLocString& aItem);
		
		TUint32 iCheckSum;
		HBufC* iData;
	};

const TUid KEnvUid = {0x20026D02};

_LIT(KLocEnv, "LOCENV");

#define Panic(x) User::Panic(KLocEnv, x)

enum 
	{
	KEnvPanicInitFailed = 1
	};

class MGLClientObserver
	{
	public:
		virtual void GLClientEvent(TInt aEventType)=0;
	};

enum TGLClientStatus
	{
	EGLConnecting = 1,
	EGLDownloadFailed,
	EGLDownloadError,
	EGLAuthFailed,
	EGLConnectionUp,
	EGLConnectionError,
	EGLGetLanguages,
	EGLGetTranslation,
	EGLGetLanguagesCompleted,
	EGLGetTranslationCompleted,
	EGLServerError
	};

_LIT8( KUserAgent, "GLClient/1.0 (Symbian)" );

class CGLClient;

class CGLClientUI : public CBase, 
					public MGLClientObserver, 
					public MProgressDialogCallback
	{
	public:
		static CGLClientUI* NewL();
		virtual ~CGLClientUI();
		
		void ChangeLanguageL();
		
		inline CGLClient* Client()
			{
			return iClient;
			}
		
	
	private:
		void GLClientEvent(TInt aEventType);
		
		void ParseLanguageList(HBufC8* aData, 
								CDesCArray& aLanguages,
								CDesC8Array& aLanguageCodes);
		
	private: // from MProgressDialogCallback
		void DialogDismissedL( TInt aButtonId );
		
	private:
		CGLClientUI();
		void ConstructL();
		
	private:
		CGLClient* iClient;
		CAknWaitDialog* iWaitDialog;
	};


class CGLClient : public CActive, 
				  public MHTTPTransactionCallback				  
	{
	public:
		static CGLClient* NewL(MGLClientObserver& aObserver);
		virtual ~CGLClient();
		
	public:
		void StartConnectionL();
		void SetAccessPoint( TInt aIapID );
		void GetLanguagesL();
		void GetTranslationL(const TDesC8& aLanguageCode);
		HBufC8* BufferPtrL();
		void CancelGet();
		
	private: // Constructors
		CGLClient( MGLClientObserver& aObserver );
		void ConstructL();
	
	private: // Helpers
		void GetL( const TDesC8& aUrl );
		void SetHeaderL( RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue );
		void SetHeaderL( RHTTPHeaders aHeaders, const TDesC8& aKey, const TDesC8& aHdrValue );
	
	private: // from MHTTPTransactionCallback
		void MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent );
		TInt MHFRunError( TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent );
	
	private: // from CActive
		void RunL();
		void DoCancel();
		
	private:
		RHTTPSession			iSession;
		RHTTPTransaction		iTransaction;
		RSocketServ				iSocketServ;
		RConnection				iConnection;
		MGLClientObserver&		iObserver;
		TBool					iActiveTransaction;
		HBufC8*					iBuffer;
		TBool					iConnUp;
		TBool					iCancelled;
		TInt					iIapID;
		TGLClientStatus			iState;
	};

#endif // LOCENV_H
